package uts.sdk.modules.droidUtil

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.provider.Settings
import android.telephony.TelephonyManager
import android.util.Log
// import androidx.annotation.RequiresApi
// import androidx.annotation.RequiresPermission
import java.security.MessageDigest
import java.util.Locale
import java.util.UUID
import android.content.SharedPreferences
import androidx.core.content.edit
// 引用 uts 基础库相关类
import io.dcloud.uts.UTSAndroid

class DeviceId {
  val TAG = "DeviceId"
  
  var _spf: SharedPreferences? = null
  var context: Context? = null
  
    init {
      try {
        context = UTSAndroid.getAppContext() as Context
        _spf = context?.getSharedPreferences("device_id_cache", Context.MODE_PRIVATE)
      } catch (e: Exception) {
        Log.e(TAG, "getInstance: error = ${e.message}")
      }
    }

  companion object {
    @Volatile
    private var instance: DeviceId? = null
    fun getInstance() =
      instance ?: synchronized(this) {
        instance ?: DeviceId().also { instance = it }
      }
  }

  //@RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE")
  //@RequiresApi(Build.VERSION_CODES.O)
  fun getDeviceId(length: Int = 16): String {
    // 先取缓存的id
    var uuid: String? = getUuidByCache()
    if(uuid != null && uuid.isNotEmpty()){
      return uuid
    }
    var deviceId = StringBuilder("")
    //获得设备默认IMEI（>=6.0 需要ReadPhoneState权限）
    val imei = getIMEI(context!!)
    Log.d(TAG, "getDeviceId: imei = $imei")
    //获得AndroidId（无需权限）
    val androidid = getAndroidId(context!!)
    Log.d(TAG, "getDeviceId: ${androidid}")
    //获得设备序列号（无需权限）
    val serial = getSerial()
    Log.d(TAG, "getDeviceId: serial : ${serial}")
    //获得硬件uuid（根据硬件相关属性，生成uuid）（无需权限）
    val deviceInfo = buildDeviceFingerprint(context!!)
    Log.d(TAG, "getDeviceId: deviceInfo : ${deviceInfo}")
    //追加imei
    if (imei.isNotEmpty()) {
      deviceId.append(imei).append('|')
    }
    //追加android id
    if (androidid.isNotEmpty()) {
      deviceId.append(androidid).append("|")
    }
    //追加serial
    if (serial.isNotEmpty()) {
      deviceId.append(serial).append('|')
    }
    //追加硬件uuid
    if (deviceInfo.isNotEmpty()) {
      deviceId.append(deviceInfo).append("|")
    }
    //生成SHA1，统一DeviceId长度
    if (deviceId.isNotEmpty()) {
      var randomPrefix = generateRandomPrefix()
      Log.d(TAG, "getDeviceId: randomPrefix $randomPrefix")
      val shaHash = sha256(deviceId.toString())
      // 前8位为0
      //uuid = UUID(shaHash.hashCode().toLong(), shaHash.hashCode().toLong()).toString()
      //Log.d(TAG, "getDeviceId: uuid =${uuid}")

      uuid = "$randomPrefix${shaHash.take(24)}"
      Log.d(TAG, "getDeviceId: uuid =${uuid}")

    } else {
      //则DeviceId默认使用系统随机数，这样保证DeviceId不为空
      uuid = UUID.randomUUID().toString().replace("-", "")
    }

    uuid =  when (length) {
      16 -> uuid.replace("-", "").take(16)
      32 -> uuid.replace("-", "")
      36 -> insertHyphens(uuid)
      64 -> sha256(uuid).substring(0, 64)
      else -> uuid.takeIf { it.length >= length } ?: uuid
    }
    this.saveUuidToCache(uuid)
    return uuid
  }

   private fun getUuidByCache(): String? {
      return getID("_uuid_")
    }
  
    /**
     * 保存uuid, 这里后期保存到sdcard中，做隐藏文件存放，避免应该卸载时uuid也被删除
     */
    private fun saveUuidToCache(uuid: String) {
      this.saveID("_uuid_", uuid)
    }
  
    fun saveID(key: String, value: String) {
      _spf?.edit(commit = true) { putString(key, value) }
    }
  
    fun getID(key: String): String {
      return _spf?.getString(key, "") ?: ""
    }
  

  //需要获得READ_PHONE_STATE权限，>=6.0，默认返回null
  //@RequiresApi(Build.VERSION_CODES.O)
  //@RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE")
  fun getIMEI(context: Context): String {
    try {
      val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
      return tm.imei ?: tm.meid
    } catch (e: Exception) {
      Log.e(TAG, "getIMEI: error $e.message")
    }
    return ""
  }

  @SuppressLint("HardwareIds")
  fun getAndroidId(context: Context): String {
    try {
      val androidId =
        Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
      return androidId ?: ""
    } catch (ex: Exception) {
      ex.printStackTrace();
      Log.e(TAG, "getAndroidId: error = ${ex.message}", ex)
    }
    return "";
  }


  fun getSerial(): String {
    try {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        return Build.getSerial()
      } else {
        return Build.SERIAL
      }
    } catch (ex: Exception) {
      Log.e(TAG, "getSERIAL: error=${ex.message}")
    }
    return "android_serial"
  }

  /**
   * 构建设备指纹
   * @return 设备系统信息
   */
  @SuppressLint("HardwareIds")
  private fun buildDeviceFingerprint(context: Context): String {
    /*
    android.os.Build.BOARD：获取设备基板名称
    android.os.Build.BOOTLOADER:获取设备引导程序版本号
    android.os.Build.BRAND：获取设备品牌
    android.os.Build.CPU_ABI：获取设备指令集名称（CPU的类型）
    android.os.Build.CPU_ABI2：获取第二个指令集名称
    android.os.Build.DEVICE：获取设备驱动名称
    android.os.Build.DISPLAY：获取设备显示的版本包（在系统设置中显示为版本号）和ID一样
    android.os.Build.FINGERPRINT：设备的唯一标识。由设备的多个信息拼接合成。
    android.os.Build.HARDWARE：设备硬件名称,一般和基板名称一样（BOARD）
    android.os.Build.HOST：设备主机地址
    android.os.Build.ID:设备版本号。
    android.os.Build.MODEL ：获取手机的型号 设备名称。
    android.os.Build.MANUFACTURER:获取设备制造商
    android:os.Build.PRODUCT：整个产品的名称
    android:os.Build.RADIO：无线电固件版本号，通常是不可用的 显示unknown
    android.os.Build.TAGS：设备标签。如release-keys 或测试的 test-keys
    android.os.Build.TIME：时间
    android.os.Build.TYPE:设备版本类型  主要为"user" 或"eng".
    android.os.Build.USER:设备用户名 基本上都为android-build
    android.os.Build.VERSION.RELEASE：获取系统版本字符串。如4.1.2 或2.2 或2.3等
    android.os.Build.VERSION.CODENAME：设备当前的系统开发代号，一般使用REL代替
    android.os.Build.VERSION.INCREMENTAL：系统源代码控制值，一个数字或者git hash值
    android.os.Build.VERSION.SDK：系统的API级别 一般使用下面大的SDK_INT 来查看
    android.os.Build.VERSION.SDK_INT：系统的API级别 数字表示
    */
    var deviceInfo = StringBuilder("")
      .append(Build.BRAND).append(":")
      .append(Build.BOARD).append(":")
      .append(Build.DEVICE).append(":")
      .append(Build.CPU_ABI).append(":")
      .append(Build.DISPLAY).append(":")
      .append(Build.HOST).append(":")
      .append(Build.HARDWARE).append(":")
      .append(Build.ID).append(":")
      .append(Build.MANUFACTURER).append(":")
      .append(Build.MODEL).append(":")
      .append(Build.PRODUCT).append(":")
      .append(Build.TAGS).append(":")
      .append(Build.TYPE).append(":")
      .append(Build.USER).append(":")
      .append(Build.VERSION.RELEASE).append(":")
      .append(Build.VERSION.CODENAME).append(":")
      .append(Build.VERSION.INCREMENTAL).append(":")
      .append(Build.VERSION.SDK).append(":")
      .append(Build.VERSION.SDK_INT)
      .append(Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID))
    Log.d(TAG, "buildDeviceFingerprint: DeviceFingerprint = $deviceInfo")
    return deviceInfo.toString()
  }


  /**
   * 取SHA1
   * @param data 数据
   * @return 对应的hash值
   */
  private fun sha1(data: String): ByteArray {
    try {
      var messageDigest = MessageDigest.getInstance("SHA-1");
      messageDigest.reset()
      messageDigest.update(data.toByteArray(Charsets.UTF_8))
      return messageDigest.digest();
    } catch (e: Exception) {
      return "".toByteArray()
    }
  }

  private fun sha256(data: String): String {
    try {
      var messageDigest = MessageDigest.getInstance("SHA-256");
      messageDigest.reset()
      messageDigest.update(data.toByteArray(Charsets.UTF_8))
      val digest = messageDigest.digest()
      return digest.joinToString("") { "%02x".format(it) }
    } catch (e: Exception) {
      return ""
    }
  }

  /**
   * 生成 8 位随机十六进制数
   * 使用时uuid每次获取都会发生变化,需要保存到本地
   */
  private fun generateRandomPrefix(): String {
//        val hexChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._"
    val hexChars = "0123456789abcdefghijklmnopqrstuvwxyz"
    return (1..8).map { hexChars.random() }.joinToString("")
  }

  /**
   * 插入横线生成标准 UUID 格式（36 位）
   * @param uuid
   */
  private fun insertHyphens(uuid: String): String {
    return try {
      "${uuid.substring(0, 8)}-${uuid.substring(8, 12)}-" +
          "${uuid.substring(12, 16)}-${uuid.substring(16, 20)}-${uuid.substring(20)}"
    } catch (e: Exception) {
      uuid
    }
  }

  /**
   * 转16进制字符串
   * @param data 数据
   * @return 16进制字符串
   */
  private fun bytesToHex(data: ByteArray): String {
    var sb = StringBuilder()
    var stmp: String? = ""
    for (i in data.indices) {
      //Log.d(TAG, "Index: $i, Value: ${data[i]}")
      stmp = Integer.toHexString(data[i].toInt() and 0xFF)
      if (stmp.length == 1)
        sb.append("0")
      sb.append(stmp)
    }
    return sb.toString().toLowerCase(Locale.CHINA)
  }

}